package com.wms.ymcc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.wms.ymcc.api.CourseAPI;
import com.wms.ymcc.constant.ValidationConstants;
import com.wms.ymcc.domain.*;
import com.wms.ymcc.dto.PlaceOrderDto;
import com.wms.ymcc.exception.GlobalBaseException;
import com.wms.ymcc.mapper.CourseOrderMapper;
import com.wms.ymcc.result.JSONResult;
import com.wms.ymcc.service.ICourseOrderItemService;
import com.wms.ymcc.service.ICourseOrderService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.wms.ymcc.util.CodeGenerateUtils;
import com.wms.ymcc.vo.CourseInfoResultVo;
import com.wms.ymcc.vo.CourseInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 阿盛哟
 * @since 2025-06-22
 */
@Slf4j
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    protected CourseAPI courseAPI;

    @Autowired
    private ICourseOrderItemService courseOrderItemService;

    @Autowired
    private CourseOrderMapper courseOrderMapper;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    @Transactional
    public String placeOrder(PlaceOrderDto placeOrderDto) {

        // 写死：登录信息写死
        Long loginId = 3l;

        // 1. 参数校验  略
        List<Long> courseIds = placeOrderDto.getCourseIds();
        Integer payType = placeOrderDto.getPayType();
        String token = placeOrderDto.getToken();
        Integer type = placeOrderDto.getType();

        // 2. token校验,与之前生成订单的内容一致
        Object redisToken = redisTemplate.opsForValue().get(ValidationConstants.REDIS_KEY_TOKEN_KEN);
        // token校验
        if(redisToken==null || !token.equals(redisToken.toString())){
            throw new GlobalBaseException("请勿重复提交该订单，稍等。。。。");
        }

        // 生成订单信息
        JSONResult jsonResult = courseAPI.courseInfoApi(courseIds);

        // String data = jsonResult.getData().toString();如果接口返回的是json对象，则需要转换成jsonString
        String jsonString = JSONObject.toJSONString(jsonResult.getData());

        CourseInfoResultVo courseInfoResultVo = JSONObject.parseObject(jsonString, CourseInfoResultVo.class);
        // 所有的课程信息
        List<CourseInfoVo> courseInfos = courseInfoResultVo.getCourseInfos();
        // 总价
        BigDecimal totalAmount = courseInfoResultVo.getTotalAmount();

        // 订单表 t_course_order
        CourseOrder courseOrder = new CourseOrder();
        Date now = new Date();
        courseOrder.setCreateTime(now);
        courseOrder.setUpdateTime(now);
        // 生成一个随机的订单编号
        String orderSn = CodeGenerateUtils.generateOrderSn(loginId);
        courseOrder.setOrderNo(orderSn);
        courseOrder.setTotalAmount(totalAmount);
        courseOrder.setTotalCount(courseInfos.size());
        // TODO 抽成常量  0: 下单未支付状态
        courseOrder.setStatusOrder(0);
        // 用户 id

        courseOrder.setUserId(loginId);
        // TODO  课程标题可以使用课程name，多个课程name拼接。
        CourseInfoVo courseInfoVo = courseInfos.get(0);
        courseOrder.setTitle(courseInfoVo.getCourse().getName());
        courseOrder.setPayType(payType);

        //insert(courseOrder);

        // 订单明细表 t_course_order_item
        for (CourseInfoVo courseInfo : courseInfos) {
            Course course = courseInfo.getCourse();
            CourseMarket courseMarket = courseInfo.getCourseMarket();
            CourseOrderItem courseOrderItem = new CourseOrderItem();
            courseOrderItem.setAmount(courseMarket.getPrice());
            courseOrderItem.setCount(1);
            courseOrderItem.setCreateTime(now);
            courseOrderItem.setUpdateTime(now);
            courseOrderItem.setCourseId(course.getId());
            courseOrderItem.setCourseName(course.getName());
            courseOrderItem.setCoursePic(course.getPic());
            courseOrderItem.setOrderNo(orderSn);
            //添加订单项
            courseOrder.getOrderItemList().add(courseOrderItem);
            // 添加订单项,放入分布式事务进行操作
            //courseOrderItemService.insert(courseOrderItem);
        }


        // 支付单对象。
        PayOrder payOrder = new PayOrder();
        // 创建时间
        payOrder.setCreateTime(now);
        // 支付金额
        payOrder.setAmount(totalAmount);
        payOrder.setPayType(payType);
        payOrder.setOrderNo(orderSn);
        payOrder.setUserId(loginId);
        payOrder.setSubject(courseOrder.getTitle());
        // 支付状态 0 未支付 1 已支付
        payOrder.setPayStatus(0);

        // 发送消息：  内容： courseOrder---》有订单和订单明细信息了。
        //消息内容到底应该长成什么样子？
        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(
                //事务监听器组名字
                ValidationConstants.MQ_COURSEORDER_PAY_GROUP_TRANSACTION,
                //主题：标签
                ValidationConstants.MQ_TOPIC_ORDER + ":" + ValidationConstants.MQ_TAGS_COURSEORDER_PAYORDER,
                //消息：用作保存支付单
                MessageBuilder.withPayload(JSONObject.toJSONString(payOrder)).build(),
                //参数：用作保存课程订单和明细
                courseOrder);

        // 发送消息检查
        if(transactionSendResult.getSendStatus()!= SendStatus.SEND_OK){
            throw new GlobalBaseException("下单失败");
        }
        log.info("下单成功：{}",transactionSendResult.getSendStatus());

        // 清除redis中的token,防止重复提交订单
        redisTemplate.delete(ValidationConstants.REDIS_KEY_TOKEN_KEN);

        return orderSn;
    }


    /**
     * 保存订单和订单明细
     * @param courseOrder
     */
    @Override
    public void saveOrderAndItem(CourseOrder courseOrder) {
        //TODO 校验一下 校验订单编号
        //1. 可以根据orderNo查询，如果查不到，则可以添加订单和订单明细
        Wrapper<CourseOrder> ww = new EntityWrapper<>();
        ww.eq("order_no",courseOrder.getOrderNo());
        CourseOrder courseOrderFormDB = selectOne(ww);
        // 如果查到，则不能添加
        if(courseOrderFormDB!=null){
            log.info("订单已存在，不能重复添加");
            throw new GlobalBaseException("订单已存在，不能重复添加");
        }
        insert(courseOrder);
        List<CourseOrderItem> orderItemList = courseOrder.getOrderItemList();
        courseOrderItemService.insertBatch(orderItemList);

    }

    @Override
    public void updateByOrderNo(String orderNo) {
        //TODO 校验一下 略
        courseOrderMapper.updateByOrderNo(orderNo);
    }
}
